; void prewitt_asm (unsigned char *src, unsigned char *dst, int h, int w, int row_size)

global prewitt_asm

%define width [ebp - 4]
%define rowsize [ebp - 8]

prewitt_asm:
    push ebp
    mov ebp, esp
    sub esp, 8                	    ; 12 bytes para local vars
    push ebx
    push edi
    push esi                	    ; stackframe

    mov esi, [ebp + 8]              ; esi = src
    mov edi, [ebp + 12]             ; edi = dst
    mov ecx, [ebp + 16]             ; ecx = heigh
    mov ebx, [ebp + 20]             ; ebx = width
    mov eax, [ebp + 24]		    ; eax = rowsize

    mov dword width, ebx            ; local width
    mov dword rowsize, eax	    ; local rowsize
    pxor xmm7, xmm7                 ; registro para extender   


    sub ecx, 2			    ; 1er y ultima fila no se procesan

    add esi, ebx		    
    add edi, ebx
			    ; fila 2 col 2

ciclo_hprewitt:
    cmp ecx, 0
    je fin

    xor ebx, ebx
    mov dword ebx, rowsize
    xor edx, edx
    mov edx, width
    sub edx, 1			    ; ebx y edx = rowsize
    inc esi
    inc edi
ciclo_wprewitt:
    cmp edx, 0                      ; si termine con la fila, voy al ciclo de h
    jle fin_fila

    cmp edx, 16
    jbe retrocederprewitt

sigo_w:
					 ; calculo derivada en x
    xor ebx, ebx
    mov dword ebx, rowsize

    movdqu xmm0, [esi + ebx + 1]	 ; abajo der
    movdqa xmm2, xmm0
    punpcklbw xmm0, xmm7
    punpckhbw xmm2, xmm7

    movdqu xmm1, [esi + 1]		 ; medio der
    movdqa xmm3, xmm1
    punpcklbw xmm1, xmm7
    punpckhbw xmm3, xmm7
    paddusw xmm0, xmm1			
    paddusw xmm2, xmm3			

    neg ebx
    movdqu xmm1, [esi + ebx + 1]	 ; arriba der: [esi - ebx + 1]
    movdqa xmm3, xmm1
    punpcklbw xmm1, xmm7
    punpckhbw xmm3, xmm7
    paddusw xmm0, xmm1 			 
    paddusw xmm2, xmm3
    neg ebx

    movdqu xmm1, [esi + ebx - 1]	 ; abajo izq
    movdqa xmm3, xmm1
    punpcklbw xmm1, xmm7
    punpckhbw xmm3, xmm7
    psubsw xmm0, xmm1
    psubsw xmm2, xmm3			 ; (abajo der - abajo izq)

    movdqu xmm1, [esi - 1]		 ; medio izq
    movdqa xmm3, xmm1
    punpcklbw xmm1, xmm7
    punpckhbw xmm3, xmm7
    psubsw xmm0, xmm1			  ; (ab der - ab izq + 2*medio der - 2*medio izq)
    psubsw xmm2, xmm3

    neg ebx	
    movdqu xmm1, [esi + ebx - 1]	 ; arriba izq 
    movdqa xmm3, xmm1
    punpcklbw xmm1, xmm7
    punpckhbw xmm3, xmm7
    psubsw xmm0, xmm1			 ; (ab der - ab izq + 2*medio der - 2*medio izq + arr der - arr izq)
    psubsw xmm2, xmm3
    neg ebx
    
    pabsw xmm0,xmm0
    pabsw xmm2,xmm2

    packuswb xmm0, xmm2			 ; en xmm0 low derivada en x,
    movdqa xmm5, xmm0	 		 ; guardo resultado de la derivada en x, en xmm5

    					 ; calculo derivada en y
    movdqu xmm0, [esi + ebx - 1]	 ; ab izq : [esi + ebx - 1]
    movdqa xmm2, xmm0
    punpcklbw xmm0, xmm7
    punpckhbw xmm2, xmm7
    
    movdqu xmm1, [esi + ebx]	 	 ; ab medio
    movdqa xmm3, xmm1
    punpcklbw xmm1, xmm7
    punpckhbw xmm3, xmm7
    paddusw xmm0, xmm1
    paddusw xmm2, xmm3

    movdqu xmm1, [esi + ebx + 1]	  ; abajo der
    movdqa xmm3, xmm1
    punpcklbw xmm1, xmm7
    punpckhbw xmm3, xmm7
    paddusw xmm0, xmm1
    paddusw xmm2, xmm3


    neg ebx				   ; ebx negativo
    movdqu xmm1, [esi + ebx - 1]	   ; arriba izq : [esi - ebx - 1]
    movdqa xmm3, xmm1
    punpcklbw xmm1, xmm7
    punpckhbw xmm3, xmm7
    psubsw xmm0, xmm1
    psubsw xmm2, xmm3

    movdqu xmm1, [esi + ebx]	    	   ; arriba medio
    movdqa xmm3, xmm1
    punpcklbw xmm1, xmm7
    punpckhbw xmm3, xmm7
    psubsw xmm0, xmm1
    psubsw xmm2, xmm3

    movdqu xmm1, [esi + ebx + 1]     	  ; arriba der
    movdqa xmm3, xmm1
    punpcklbw xmm1, xmm7
    punpckhbw xmm3, xmm7
    psubsw xmm0, xmm1
    psubsw xmm2, xmm3

    pabsw xmm0,xmm0
    pabsw xmm2,xmm2

    packuswb xmm0, xmm2			  ; xmm0 y xmm2 lo y hi de la derivada en y
    paddusb xmm5, xmm0	 	          ; sumo el resultado de la derivada en y, a la derivada en x

    movdqu [edi], xmm5
    add esi, 16
    add edi, 16
    sub edx, 16
    jmp ciclo_wprewitt


retrocederprewitt:                       
    xor eax, eax
    mov dword eax, 16        
    sub eax, edx                   ; (ebx < 16) -> (16 - ebx > 0)
    sub esi, eax                   ; corro el puntero para atras
    sub edi, eax
    mov dword edx, 16		   ; para q salte a fin_fila dps
jmp sigo_w

fin_fila:
    dec ecx
jmp ciclo_hprewitt
    
fin:
    pop esi                        ; desarmo el stack frame
    pop edi          
    pop ebx
    add esp, 8
    pop ebp
    ret
